const {ControlParameters} = require("../component/ControlParameters");
const {createIdentifierComponentByByteArray} = require("../component/IdentifierComponent");
const {createIdentifierByString} = require("../component/Identifier");
const {Interest} = require("../packet/Interest");
const {Encoder, MaxPacketSize} = require('../encoding').Encoder
const {createBlockByBuffer} = require('../encoding/Block')
const aggregation = require('../common/aggregation')
const {IControlCommand} = require("./IControlCommand");

//实现了多继承
// CommandBase 表示一个控制管理的命令的通用结构
/**
 * @description:
 * eg. /min-mir/mgmt/localhost/face-mgmt/list
 * - topPrefix => /min-mir/mgmt/localhost
 *	- moduleName => face-mgmt
 *	- action => list
 */

const ManagementModuleFaceMgmt = "face-mgmt"
const ManagementModuleFibMgmt = "fib-mgmt"
const ManagementModuleCsMgmt = "cs-mgmt"
const ManagementModuleIdentityMgmt = "identity-mgmt"
class CommandBase extends aggregation(IControlCommand){
    constructor() {
        super()
        this.topPrefix = ""
        this.moduleName = ""
        this.action = ""
        this.parameters = null
    }

    /**
     * GetTopPrefix 获取顶级前缀
     * @returns {string}
     */
    getTopPrefix(){
        return this.topPrefix;
    }

    /**
     * SetTopPrefix 设置顶级前缀
     * @param topPrefix
     */
    setTopPrefix(topPrefix){
        this.topPrefix = topPrefix
    }

    /**
     * GetModuleName 获取模块名称
     * @returns {string}
     */
    getModuleName(){
        return this.moduleName
    }

    /**
     * SetModuleName 设置模块名称
     * @param moduleName
     */
    setModuleName(moduleName){
        this.moduleName = moduleName
    }

    /**
     * GetAction 获取命令动作
     * @returns {string}
     */
    getAction(){
        return this.action
    }

    /**
     * SetAction 设置命令动作
     * @param action
     */
    setAction(action){
        this.action = action
    }

    /**
     * GetParameters 获取管理命令前缀
     */
    getParameters(){
        return this.parameters
    }

    /**
     * SetParameters 设置管理命令前缀
     * @param parameters
     */
    setParameters(parameters){
        this.parameters = parameters
    }
}
/**
 * @description 根据传入的控制参数和前缀创建一个命令兴趣包
 * @param parameters {ControlParameters}
 * @param prefix {String}
 * @returns {Interest}
 */
function createCommandIdentifierInterest(parameters, prefix){
    // /min-mir/mgmt/localhop/<模块名称>/<命令>/<参数>/[版本号]/[分片号]
    let interest = new Interest()
    let commandIdentifier = createIdentifierByString(prefix)

    let enc = new Encoder()
    enc.encoderReset(MaxPacketSize, 0)
    parameters.wireEncode(enc)

    let controlParameterBuf = enc.getBuffer()
    commandIdentifier.append(createIdentifierComponentByByteArray(controlParameterBuf))
    interest.setName(commandIdentifier)
    return interest
}

/**
 * @description 根据传入的命令兴趣包解析出一个控制参数
 * @param interest {Interest}
 * @returns {ControlParameters}
 */
function parseControlParameters(interest) {
    let cp = new ControlParameters()
    let identifier = interest.getName();
    let components = identifier.getComponents();
    let length = components.length;
    if (length >= 3) {
        if (components[length - 1].isByteArray()) {
            let block = createBlockByBuffer(components[length - 1].getByteArray(), true)
            cp.wireDecode(block)
        } else if (components[length - 1].isFragmentNumber()
            && components[length - 2].isVersionNumber()
            && components[length - 3].isByteArray()) {
            let block = createBlockByBuffer(components[length - 3].getByteArray(), true)
        } else {
            throw new ControlParametersError()
        }
    } else {
        throw new ControlParametersError()
    }
    return cp
}

class ControlParametersError extends Error {
    constructor(m) {
        super(m)
        this.name = 'ControlParametersError'
    }

    error() {
        console.log(`${this.name}: ${this.message}`)
    }
}

module.exports = {
    createCommandIdentifierInterest: createCommandIdentifierInterest,
    parseControlParameters: parseControlParameters,
    CommandBase: CommandBase,
    ManagementModuleFaceMgmt: ManagementModuleFaceMgmt,
    ManagementModuleFibMgmt: ManagementModuleFibMgmt,
    ManagementModuleCsMgmt: ManagementModuleCsMgmt,
    ManagementModuleIdentityMgmt: ManagementModuleIdentityMgmt
}
